/***********************************************
 * Filename:  		Renderer.h
 * Date:      		???
 * Mod. Date: 		???
 * Mod. Initials:	MVP
 * Author:    		Mikeal V. Perry
 * Purpose:   		Handles rendering of all objects
 ************************************************/

#ifndef _RENDERER_H
#define _RENDERER_H

#include "..//Resource.h"

#include <vector>
#include <map>
#include <string>


// DirectX9 includes and libraries
#include <d3d9.h>
#include <d3dx9.h>
#include <d3dx9math.h>

#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")


// Forward Declarations
class CTimer;
class CMaterial;
class CShaderBase;
class CModel;
struct TMesh;
struct TMaterial;

class CRenderer
{
	// Enum used for shader identification
	enum eShaderNames {SN_POS, SN_POS_NORM, NUM_OF_SHADERS};

	///////////////////////////////////////
	//		Line Struct
	///////////////////////////////////////
	struct tLineVert
	{
		float fX, fY, fZ;
	};


	///////////////////////////////////////
	//		Private Variables
	///////////////////////////////////////

	// Window information
	HWND						m_hWindowHandle;

	// DirectX Initialization members
	IDirect3D9					*m_pd3dObject;
	IDirect3DDevice9			*m_pd3dDevice;
	ID3DXSprite					*m_pd3dSpriteManager;
	ID3DXFont					*m_pd3dFont;

	// Declarations for the buffers used (Non-Interleaved)
	IDirect3DVertexBuffer9		*m_pd3dPositionBuffer;
	IDirect3DVertexBuffer9		*m_pd3dNormalBuffer;
	IDirect3DVertexBuffer9		*m_pd3dTexCoordBuffer;
	IDirect3DVertexBuffer9		*m_pd3dTangentBuffer;
	IDirect3DIndexBuffer9		*m_pd3dIndexBuffer;
	IDirect3DVertexDeclaration9	*m_pd3dVertexDecl;

	// Matrices used for determining placement
	D3DXMATRIX					m_d3dWorldMatrix;
	D3DXMATRIX					m_d3dCameraMatrix;
	D3DXMATRIX					m_d3dProjectionMatrix;

	// Vectors used to store the incoming vertices and indices of this frame
	// Used to populate this frame's vertex and index buffer
	std::vector<D3DXVECTOR3>	m_Vertices;
	std::vector<D3DXVECTOR3>	m_Normals;
	std::vector<D3DXVECTOR2>	m_TexCoords;
	std::vector<D3DXVECTOR3>	m_Tangents;
	std::vector<unsigned int>	m_Indices;

	// A vector to store lines in as well as a buffer to display them
	std::vector<tLineVert>		m_vLineArray;
	IDirect3DVertexBuffer9		*m_pd3dLineBuffer;
	ID3DXEffect					*m_pd3dLineEffect;

	// Vector used to store the models with information
	std::vector<CModel>			m_vModelBank;

	// Vector used to store the mesh information for rendering models
	std::vector<TMesh>			m_MeshBank;

	// Vector used to store the shader information for loaded shaders
	std::vector<ID3DXEffect*>	m_vd3dShaderBank;

	// Vector used to store the information for loaded 2D textures
	std::vector<std::pair<std::string, IDirect3DTexture9*>>		m_vd3dTextureBank;

	// Vector used to store the information for loaded cube maps
	std::vector<std::pair<std::string, IDirect3DCubeTexture9*>>	m_vd3dCubeMapBank;

	// Vector that stores shader with objects to be rendered
	std::vector<CShaderBase>	m_vRenderSet;

	// The timer pointer
	CTimer*		m_pTimer;


	///////////////////////////////////////
	//		Private Functions
	///////////////////////////////////////
	
	// Private constructor and destructor
	CRenderer(void);
	~CRenderer(void);

	// Renders the text for meta information
	int RenderFrameInfo();

	// Creates the buffers and declarations used in these 'universal' buffers. Should be called at load time and loads all models.
	int CreateBuffers();					// Establishes which objects need to be in these buffers. Load time call.
	int BuildPositionBuffer();				// Builds the Position Buffer for use with rendering objects that have positions
	int BuildNormalBuffer();				// Builds the Normal Buffer for use with rendering objects that have normals
	int BuildTexCoordBuffer();				// Builds the TexCoords Buffer for use with rendering objects that have TexCoords
	int BuildTangentBuffer();				// Builds the Tangent Buffer for use with rendering objects that have TexCoords Tangents
	int BuildIndexBuffer();					// Builds the Index Buffer for use with rendering objects that have indices

	// Functions used during the render process to help make the code more organized
	int SetStreamSources(TMesh* tMesh, int nUsage);

	// Functions for loading in each bank
	int LoadModelBank(const char* szFilePath);					// Loads the model bank
	int LoadShaderBank(const char* szFilePath);					// Loads the shader bank
	int LoadTextureBank(const char* szFilePath);				// Loads the 2D texture bank
	int LoadCubeMapBank(const char* szFilePath);				// Loads the cube map texture bank
	int LoadMesh(const char* szFilePath, const char* szMeshName,  int nBufferField);		// Loads the detailed mesh data of the model

	// Renders the contents of the lines buffer Mostly used in Debug
	void FlushLines();

	// PLACEHOLDER FUNCTIONS AND VARIABLES
	

public:

	/*****************************************************************
	* GetInstance():	Gets the instance of the Renderer
	*
	* Ins:
	* Outs:
	* Returns:			CRenderer*
	*
	* Mod. Date:		???
	* Mod. Initials:	MVP
	*****************************************************************/
	static CRenderer *GetInstance();

	/*****************************************************************
	* Initialize():		Initializes the DirectX systems
	*
	* Ins:				hWnd
	*					nWidth
	*					nHeight
	*					bIsWindowed
	*					szModelBankPath
	*					szShaderBankPath
	* Outs:
	* Returns:			int
	*
	* Mod. Date:		???
	* Mod. Initials:	MVP
	*****************************************************************/
	int Initialize(HWND hWnd, unsigned int nWidth, unsigned int nHeight, bool bIsWindowed);

	/*****************************************************************
	* Shutdown():		Shuts down the DirectX systems
	*
	* Ins:				
	* Outs:
	* Returns:
	*
	* Mod. Date:		???
	* Mod. Initials:	MVP
	*****************************************************************/
	void Shutdown();

	/*****************************************************************
	* GetInstance():	Renders all objects in set
	*
	* Ins:				fElapsedTime
	* Outs:
	* Returns:			int
	*
	* Mod. Date:		???
	* Mod. Initials:	MVP
	*****************************************************************/
	int RenderObjects(float fElapsedTime);

	/*****************************************************************
	* GetModelInfo():	Fills out the model's info 
	*					Returns -1 if not found
	*
	* Ins:				szModelName
	*					cModel
	* Outs:
	* Returns:			int
	*
	* Mod. Date:		???
	* Mod. Initials:	MVP
	*****************************************************************/
	int GetModelInfo(const char* szModelName, CModel& cModel);

	/*****************************************************************
	* AddModelToSet():	Adds the model to the shader's set
	*
	* Ins:				cMesh
	* Outs:
	* Returns:			
	*
	* Mod. Date:		???
	* Mod. Initials:	MVP
	*****************************************************************/
	void AddModelToSet(const CModel& cModel);

	/*****************************************************************
	* AddLines():		Add lines (Mainly for AABBS)
	*
	* Ins:				
	* Outs:
	* Returns:			
	*
	* Mod. Date:		???
	* Mod. Initials:	MVP
	*****************************************************************/
	void AddLines(D3DXVECTOR3 d3dPointA, D3DXVECTOR3 d3dPointB);


	/***************
	*  Accessors
	***************/
	ID3DXEffect* GetEffectFromBank(unsigned int nIndex) {return m_vd3dShaderBank[nIndex];}
	IDirect3DTexture9* GetTextureFromBank(unsigned int nIndex) {return m_vd3dTextureBank[nIndex].second;}
	IDirect3DCubeTexture9* GetCubeMapFromBank(unsigned int nIndex) {return m_vd3dCubeMapBank[nIndex].second;}

	/***************
	*  Mutators
	***************/


};
#endif